package com.ebt.m.proposal_v2.ui.function;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.ebt.m.commons.utils.Logger;
import com.ebt.m.data.entity.Customer;
import com.ebt.m.proposal_v2.base.Constant;
import com.ebt.m.proposal_v2.bean.ApplicantEntity;
import com.ebt.m.proposal_v2.bean.ArgProductOption;
import com.ebt.m.proposal_v2.bean.InsuranceCalculator;
import com.ebt.m.proposal_v2.bean.InsuranceEntity;
import com.ebt.m.proposal_v2.bean.InsuredEntity;
import com.ebt.m.proposal_v2.bean.event.ExemptResetEvent;
import com.ebt.m.proposal_v2.bean.event.NormalRiskCompleteEvent;
import com.ebt.m.proposal_v2.bean.event.UpdaterFailEvent;
import com.ebt.m.proposal_v2.helper.WebViewCallback;
import com.ebt.m.proposal_v2.ui.ProposalNativeAPI;
import com.ebt.m.proposal_v2.ui.view.InsuranceView;
import com.ebt.m.proposal_v2.utils.DataUtils;
import com.ebt.m.proposal_v2.utils.DateUtils;
import com.ebt.m.proposal_v2.widget.dialog.EBTBottomWebDialog;
import com.ebt.m.proposal_v2.widget.view.InsuranceCellView;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.List;

import static com.ebt.m.proposal_v2.ProposalConstant.EXEMPTION_TYPE_APPLICANT;
import static com.ebt.m.proposal_v2.ProposalConstant.RISK_TYPE_EXEMPT;
import static com.ebt.m.proposal_v2.ProposalConstant.RISK_TYPE_GUARANTEE_APPLICANT;

/**
 * 用于处理普通附加险的更新，更新完成后，发事件，开始更新豁免险
 *
 * @author archer
 */
public class InsuranceCellViewUpdater extends SingleWorkerForNormalRisk implements JsLoadSuccessListener {

    private Handler mMoveDataHandler;

    private WebViewStack mWebViewStack;
    private ViewStack mViewStack;

    public InsuranceCellViewUpdater(Context context, InsuranceView view) {
        this.mContext = context;
        mWebViewStack = new WebViewStack();
        mViewStack = new ViewStack();
    }

    private InsuranceView insuranceView;

    public void updateCellViewExceptExempt(List<InsuranceCellView> mExemptCellViewSet,
                                           ApplicantEntity applicantEntity,
                                           InsuredEntity insuredEntity,
                                           Customer applicant,
                                           Customer insured,
                                           InsuranceView insuranceView) {
        this.insuranceView = insuranceView;
        for (InsuranceCellView cellView : mExemptCellViewSet) {
            createNewTask(applicantEntity, insuredEntity, applicant, insured, cellView);
        }
    }

    private String createWebUrl(ArgProductOption arg) {
        if (arg == null) {
            return Constant.PROPOSAL_CALCULATOR_WEB_URL;
        }
        try {
            StringBuffer urlBuffer = new StringBuffer(Constant.PROPOSAL_CALCULATOR_WEB_URL);
            urlBuffer.append("proId=").append(DataUtils.encodeParamValue(arg.productId + "")).append("&");
            urlBuffer.append("age=").append(DataUtils.encodeParamValue(arg.age)).append("&");
            urlBuffer.append("sex=").append(DataUtils.encodeParamValue(arg.sex)).append("&");
            urlBuffer.append("profession=").append(DataUtils.encodeParamValue(arg.profession)).append("&");
            urlBuffer.append("birthday=").append(DataUtils.encodeParamValue(arg.birthday)).append("&");
            if (arg.isExemptRisk) {
                urlBuffer.append("isExempt=true").append("&");
            }
            urlBuffer.append("options=").append(DataUtils.encodeParamValue(arg.createOptionsJson()));
            return urlBuffer.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return Constant.PROPOSAL_CALCULATOR_WEB_URL;
    }

    private ArgProductOption createProductOptionArg(ApplicantEntity applicantEntity, InsuredEntity insuredEntity, InsuranceEntity product) {
        if (product == null) {
            return null;
        }
        ArgProductOption arg = new ArgProductOption();
        arg.productId = product.productId + "";
        arg.productName = product.productName;

        if (product.riskType == RISK_TYPE_GUARANTEE_APPLICANT ||
                (product.riskType == RISK_TYPE_EXEMPT && product.getExemptionType() == EXEMPTION_TYPE_APPLICANT)) {
            // 如果是普通附加险，指定被保人为投保人，或者豁免险，且豁免投保人。
            arg.age = applicantEntity == null ? "30" : applicantEntity.age + "";
            arg.sex = applicantEntity == null ? "1" : applicantEntity.sex + "";
            arg.profession = "1";
            arg.birthday = applicantEntity == null ? "" : applicantEntity.birthday;
        } else {
            // 如果是豁免险，且豁免被保人；或者不是豁免险
            arg.age = insuredEntity == null ? "30" : insuredEntity.age + "";
            arg.sex = insuredEntity == null ? "1" : insuredEntity.sex + "";
            arg.profession = insuredEntity == null ? "1" : insuredEntity.profession + "";
            arg.birthday = insuredEntity == null ? "" : insuredEntity.birthday;
        }

        if (product.riskType == RISK_TYPE_EXEMPT) {
            // 添加豁免险标识
            arg.isExemptRisk = true;
        }

        arg.coverage = product == null ? null : product.coverage;
        arg.premium = product == null ? null : product.premium;
        arg.coveragePeriod = product == null ? null : product.coveragePeriod;
        arg.paymentPeriod = product == null ? null : product.paymentPeriod;

        arg.extraOptions = product == null ? null : product.extraData;

        return arg;
    }

    private ArgProductOption createProductOptionArg(InsuranceEntity product, Customer customer) {
        if (product == null) {
            return null;
        }
        ArgProductOption arg = new ArgProductOption();
        arg.productId = product.productId + "";
        arg.productName = product.productName;

        arg.age = customer == null ? "30" : customer.getAge() + "";
        arg.sex = customer == null ? "1" : customer.getSex() + "";
        arg.profession = customer == null ? "1" : customer.getCareerCategory() + "";
        arg.birthday = customer == null ? "" : DateUtils.formatDate(customer.getBirthday());

        arg.coverage = product == null ? null : product.coverage;
        arg.premium = product == null ? null : product.premium;
        arg.coveragePeriod = product == null ? null : product.coveragePeriod;
        arg.paymentPeriod = product == null ? null : product.paymentPeriod;

        arg.extraOptions = product == null ? null : product.extraData;
        return arg;
    }

    private InsuranceCalculator parseCalculator(String json) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        InsuranceCalculator calculator = new InsuranceCalculator();
        try {
            JSONObject jsonObject = new JSONObject(json);
            JSONArray optionArr = jsonObject.getJSONArray("options");
            if (optionArr == null || optionArr.length() == 0) {
                return null;
            }
            for (int i = 0; i < optionArr.length(); i++) {
                JSONObject option = optionArr.getJSONObject(i);
                if (option != null) {
                    calculator.init(option.getString("fieldName"), option.getString("displayName"), option.getString("value"));
                }
            }
            return calculator;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更新指定豁免险的保额与保费
     *
     * @param view      豁免险的View
     * @param applicant 投保人
     * @param insured   被保人
     */
    private void updateExemptionView(InsuranceCellView view, Customer applicant, Customer insured) {
        if (view == null) {
            recycleTask();
            return;
        }
        InsuranceEntity exemptData = view.getData();
        if (exemptData == null) {
            recycleTask();
            return;
        }
        InsuredEntity insuredEntity = DataUtils.toInsured(insured);
        ApplicantEntity applicantEntity = DataUtils.toApplicant(applicant);
        String calculatorUrl = createWebUrl(createProductOptionArg(applicantEntity, insuredEntity, view.getData()));
        WebViewStack.WebViewObject webViewObject = createWebViewObject(calculatorUrl);
        if (webViewObject == null) {
            recycleTask();
            return;
        }
        Logger.i("Url [" + webViewObject.id + "] = " + calculatorUrl);
        view.setTag(webViewObject.id);
        mViewStack.put(webViewObject.id, view, exemptData); // 调用Js的线程在JsBridge线程，会导致View更新混乱；此处id绑定View,来对应正确的View

        mMoveDataHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg == null) {
                    return;
                }
                switch (msg.what) {
                    case 1:
                        WebViewCallback callback = (WebViewCallback) msg.obj;
                        calculatePremiumByJs(callback);
                        break;
                    case -1:
                        EventBus.getDefault().post(new UpdaterFailEvent());
//                    view.setData(exemptData);
//                    recycleTask();
                        break;
                }
            }
        };
    }

    /**
     * 生成一个WebViewObject对象
     *
     * @param url
     * @return
     */
    private WebViewStack.WebViewObject createWebViewObject(String url) {
        WebView webview = new WebView(mContext);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
                if (mMoveDataHandler != null) {
                    mMoveDataHandler.sendEmptyMessage(-1);
                }
            }
        });

        ProposalNativeAPI nativeAPI = new ProposalNativeAPI(mContext, this);
        WebViewCallback callback = new WebViewCallback()
                .with(webview)
                .addNativeInterface(nativeAPI, Constant.JSCallInstance);

        webview.loadUrl(url);

        WebViewStack.WebViewObject object = mWebViewStack.put(url, webview, callback);
        if (object != null && object.callback != null) {
            nativeAPI.setTag(object.callback.getId());
            nativeAPI.setUrl(object.callback.getTag());
        }

        return object;
    }

    /**
     * 解析Js结果
     *
     * @param id
     * @param calculator
     */
    private void parseJsResult(int id, InsuranceCalculator calculator) {
        ViewStack.ViewObject viewObject = mViewStack.getViewObject(id);
        if (viewObject == null || viewObject.isNull()) {
            return;
        }
        InsuranceEntity data = viewObject.data;
        if (calculator != null) {
            /* 将计算器返回的基础选项添加到data*/
            data.coverage = calculator.optCoverage;
            data.premium = calculator.optPremium;
            data.coveragePeriod = calculator.optCoveragePeriod;
            data.paymentPeriod = calculator.optPaymentPeriod;
            /* 将计算器返回的其余选项添加到data*/
            data.addExtraData(calculator.mOptionList);
        }
        InsuranceCellView cellView = viewObject.view;
        if (cellView == null) {
            return;
        }
        cellView.setData(data);
        mViewStack.remove(id);
        EventBus.getDefault().post(new ExemptResetEvent());
    }

    /**
     * 通过轮询方式调用Js计算保费
     */
    private void calculatePremiumByJs(WebViewCallback callback) {
        if (callback == null) {
            recycleTask();
            return;
        }
        callback.addJsInterface(EBTBottomWebDialog.JSGetProductOptions, response -> {
            if (response == null || "".equals(response) || "null".equals(response)) {
                mWebViewStack.remove(callback.getId(), callback.getTag());
                recycleTask();
                return;
            }
            InsuranceCalculator calculator = parseCalculator(response);
            parseJsResult(callback.getId(), calculator);
            mWebViewStack.remove(callback.getId(), callback.getTag());
            recycleTask();
        });
    }

    /**
     * 销毁
     */
    public void destroyView() {
        mWebViewStack.clearAll();
        if (mViewStack != null) {
            mViewStack.clearAll();
        }
        clearTasks();
    }

    @Override
    public void onJsLoadSuccess(int id, String url) {
        WebViewStack.WebViewObject currentWebViewObject = mWebViewStack.get(id, url);
        if (currentWebViewObject != null) {
            Message msg = new Message();
            msg.what = 1;
            msg.obj = currentWebViewObject.callback;
            mMoveDataHandler.sendMessage(msg);
        } else {
            recycleTask();
        }
    }

    @Override
    public void start(ExemptTask task) {
        if (task != null) {
            showProgress();
            updateExemptionView(task.cellView, task.applicant, task.insured);
        } else {
            completeAllTask(true, true);
        }
    }

    @Override
    public void completeAllTask(boolean refreshPremium, boolean verifyProposal) {
        super.completeAllTask(refreshPremium, verifyProposal);
        EventBus.getDefault().post(new NormalRiskCompleteEvent(refreshPremium, verifyProposal, insuranceView));
    }

    public void clearInsuranceViewRef() {
        insuranceView = null;
    }

    public void stopWebViewLoading() {
        try {
            dismissProgress();
            if (mWebViewStack != null) {
                List<WebViewStack.WebViewObject> list = mWebViewStack.getWebViewObjectStack();
                if (list != null) {
                    for (WebViewStack.WebViewObject item : list) {
                        if (item.webview != null) {
                            item.webview.stopLoading();
                        }
                    }
                }
                list.clear();
            }
            clearTasks();
        } catch (Exception e) {

        }
    }
}
